﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MIAP.DataAccess.Interfaces;
using MIAP.Entidades;
using MIAP.DataAccess.SqlServer.Model;
using MIAP.Entidades.Enums;

namespace MIAP.DataAccess.Implementaciones.SQL
{
    /// <summary>
    /// Clase de las operaciones de acceso a datos para el módulo de usuarios.
    /// </summary>
    public class UsuarioDao : IUsuarioDao
    {
        #region Operaciones relacionadas a la vista AdministraUsuario

        /// <summary>
        /// Obtiene las lista de usuarios activos registrados en el sistema.
        /// </summary>
        /// <returns>Lista de objetos usuarioInfo.</returns>
        public IList<UsuarioInfo> GetUsuarios()
        {
            IList<UsuarioInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = from usuario in context.usp_ObtenDatosUsuarioSistema(null, null)
                            select new UsuarioInfo
                            {
                                IdentificadorPortal = usuario.Clave,
                                IdUsuario = usuario.ID_USUARIO,
                                NombreUsuario = usuario.Nombre,
                                AliasUsuario = usuario.Usuario,
                                ApellidoMaterno = usuario.ApellidoMaterno,
                                ApellidoPaterno = usuario.ApellidoPaterno,
                                Estatus = usuario.Activo ? "Activo" : "Inactivo",
                                Area = usuario.Area,
                                SubArea = usuario.SubArea,
                                FechaRegistro = usuario.FechaCreacion.ToShortDateString()
                            };
                result = query.ToList();
            }

            return result;
        }

        /// <summary>
        /// Obtiene todos los usuarios que umplan con los filtros.
        /// </summary>
        /// <param name="usuarioInfo">Filtros que se aplicarán en la búsqueda.</param>
        /// <returns>Lista de usuarios.</returns>
        public IList<UsuarioInfo> GetSingleUsuarios(UsuarioInfo usuarioInfo)
        {
            IList<UsuarioInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = from usuario in context.usp_ObtenDatosUsuarioSistema(null, null)
                            where (string.IsNullOrEmpty(usuarioInfo.NombreUsuario) || usuario.Nombre.ToLower().Contains(usuarioInfo.NombreUsuario.ToLower()))
                            && (string.IsNullOrEmpty(usuarioInfo.ApellidoPaterno) || usuario.ApellidoPaterno.ToLower().Contains(usuarioInfo.ApellidoPaterno.ToLower()))
                            && (string.IsNullOrEmpty(usuarioInfo.ApellidoMaterno) || (!String.IsNullOrEmpty(usuario.ApellidoMaterno) ? usuario.ApellidoMaterno.ToLower().Contains(usuarioInfo.ApellidoMaterno.ToLower()) : usuario.ApellidoMaterno == ""))
                            && (string.IsNullOrEmpty(usuarioInfo.AliasUsuario) || usuario.Usuario.ToLower().Contains(usuarioInfo.AliasUsuario.ToLower()))
                            && (!usuarioInfo.EstaActivo.HasValue || usuario.Activo == usuarioInfo.EstaActivo)
                            select new UsuarioInfo
                            {
                                IdentificadorPortal = usuario.Clave,
                                IdUsuario = usuario.ID_USUARIO,
                                NombreUsuario = usuario.Nombre,
                                AliasUsuario = usuario.Usuario,
                                ApellidoMaterno = usuario.ApellidoMaterno,
                                ApellidoPaterno = usuario.ApellidoPaterno,
                                Estatus = usuario.Activo ? "Activo" : "Inactivo",
                                Area = usuario.Area,
                                SubArea = usuario.SubArea,
                                FechaRegistro = usuario.FechaCreacion.ToShortDateString()
                            };
                result = query.ToList();
            }

            return result;
        }

        #endregion


        /// <summary>
        /// Obtiene todos los usuarios del active directory que no han sido dados de alta en el sitema.
        /// </summary>
        /// <returns>Lista de los usuarios que aún no han sido dados de alta.</returns>
        public IList<UsuarioInfo> GetUsuariosToEnlist()
        {
            IList<UsuarioInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = from usuarioAC in context.usp_ObtenDatosUsuario(null, null)
                            where !(from usuarioMIAP in context.MIAP_USUARIO select usuarioMIAP.ID_PORTAL).Contains(usuarioAC.Clave)
                            select new UsuarioInfo
                            {
                                IdentificadorPortal = usuarioAC.Clave,
                                NombreCompleto = string.Format("{0}, {1}, {2}", usuarioAC.Nombre, usuarioAC.ApellidoPaterno, usuarioAC.ApellidoMaterno),
                                NombreUsuario = usuarioAC.Nombre,
                                ApellidoMaterno = usuarioAC.ApellidoMaterno,
                                ApellidoPaterno = usuarioAC.ApellidoPaterno,
                                AliasUsuario = usuarioAC.Usuario,
                                Area = usuarioAC.Area,
                                SubArea = usuarioAC.SubArea
                            };

                result = query.ToList();
            }

            return result;
        }  

        /// <summary>
        /// Cambia el estatus de un usuario De activo a inactivo o viceversa.
        /// </summary>
        /// <param name="idUsuario">Id del usuario del cual se cambiará el estatus.</param>
        /// <param name="estatusRegistro">Es el estatus que se le pondrá al usuario.</param>
        public void ChangeEstatusUsuario(int idUsuario, bool estatusRegistro)
        {
            using (var context = new MIAPDBEntities())
            {
                var query = (from usuario in context.MIAP_USUARIO
                             where usuario.ID_USUARIO == idUsuario
                             select usuario).Single();

                query.ACTIVO = estatusRegistro;
                context.SaveChanges();
            }
        }


        /// <summary>
        /// Obtiene el usuario del active directory dado un Id específico.
        /// </summary>
        /// <param name="idClave">Id del usuario en la tabla del AD a obtener.</param>
        /// <returns>Usuario que cumple con el filtro.</returns>
        public UsuarioInfo GetUsuarioADByClave(int idClave)
        {
            UsuarioInfo result;

            using (var context = new MIAPDBEntities())
            {
                var query = from usuarioAc in context.usp_ObtenDatosUsuario(idClave, null)                            
                            select new UsuarioInfo
                            {
                                IdentificadorPortal = usuarioAc.Clave,
                                NombreCompleto = string.Format("{0}, {1}, {2}", usuarioAc.Nombre, usuarioAc.ApellidoPaterno, usuarioAc.ApellidoMaterno),
                                NombreUsuario = usuarioAc.Nombre,
                                ApellidoMaterno = usuarioAc.ApellidoMaterno,
                                ApellidoPaterno = usuarioAc.ApellidoPaterno,                                
                                AliasUsuario = usuarioAc.Usuario,
                                Area = usuarioAc.Area,
                                SubArea = usuarioAc.SubArea,
                                DireccionCorreo = usuarioAc.Email
                            };

                result = query.SingleOrDefault();
            }

            return result;
        }

        /// <summary>
        /// Obtiene el usuario dado un Id específico.
        /// </summary>
        /// <param name="idUsuario">Id del usuario a obtener.</param>
        /// <returns>Usuario que cumple con el filtro.</returns>
        public UsuarioInfo GetUsuarioById(int idUsuario)
        {
            UsuarioInfo result;

            using (var context = new MIAPDBEntities())
            {
                var query = (from usuario in context.usp_ObtenDatosUsuarioSistema(null, null)
                             where usuario.ID_USUARIO == idUsuario
                             select new UsuarioInfo
                             {
                                 IdentificadorPortal = usuario.Clave,
                                 IdUsuario = usuario.ID_USUARIO,
                                 NombreUsuario = usuario.Nombre,
                                 AliasUsuario = usuario.Usuario,
                                 ApellidoMaterno = usuario.ApellidoMaterno,
                                 ApellidoPaterno = usuario.ApellidoPaterno,
                                 EstaActivo = usuario.Activo,
                                 Area = usuario.Area,
                                 SubArea = usuario.SubArea,
                                 DireccionCorreo = usuario.Email
                             }).Single();

                result = query;
            }

            return result;
        }

        /// <summary>
        /// Obtiene os permisos dependiendo del perfil.
        /// </summary>
        /// <param name="idPerfil">Es el id del perfil.</param>
        /// <returns>Lista de permisos.</returns>
        public IList<PermisoInfo> GetPerfilPermisosByIdPerfil(int idPerfil)
        {
            var result = new List<PermisoInfo>();

            using (var context = new MIAPDBEntities())
            {
                var query = from perfilPermiso in context.MIAP_PERFIL_URL_PERFIL
                            join permiso in context.MIAP_PERFIL_URL on perfilPermiso.ID_PERFIL equals
                                permiso.ID_PERFIL_URL
                            where perfilPermiso.ID_PERFIL == idPerfil
                            select new PermisoInfo
                                {
                                    Identificador = permiso.ID_PERFIL_URL,
                                    Nombre = permiso.NOMBRE,
                                    Url = permiso.URL
                                };

                result.AddRange(query.ToList());

            }

            return result;
        }

        /// <summary>
        /// Obtiene los usuarios que autorizan la recarga del archivo
        /// </summary>
        /// <param name="idArchivo">id del archivo del quien buscaremos los usuarios que autorizan</param>
        /// <returns>Lista de usuarios que autorizan la recarga de arhivos</returns>
        public IList<UsuarioInfo> GetUsuariosAutorizan(int idArchivo)
        {
            IList<UsuarioInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var ids = (from usuarioArchivo in context.MIAP_USUARIO_ARCHIVO
                           where usuarioArchivo.ID_ARCHIVO == idArchivo && usuarioArchivo.ES_AUTORIZACION
                           select usuarioArchivo.ID_USUARIO).ToList();

                var query = from usuario in context.usp_ObtenDatosUsuarioSistema(null, null)
                            where ids.Contains(usuario.ID_USUARIO)
                            select new UsuarioInfo
                            {
                                IdentificadorPortal = usuario.Clave,
                                IdUsuario = usuario.ID_USUARIO,
                                NombreUsuario = usuario.Nombre,
                                AliasUsuario = usuario.Usuario,
                                ApellidoMaterno = usuario.ApellidoMaterno,
                                ApellidoPaterno = usuario.ApellidoPaterno,
                                EstaActivo = usuario.Activo,
                                Area = usuario.Area,
                                SubArea = usuario.SubArea
                            };
                result = query.ToList();
            }

            return result;
        }

        /// <summary>
        /// Obtiene los usuarios que cargan la recarga del archivo
        /// </summary>
        /// <param name="idArchivo">id del archivo del quien buscaremos los usuarios que autorizan</param>
        /// <returns>Lista de usuarios que autorizan la recarga de arhivos</returns>
        public IList<UsuarioInfo> GetUsuariosCargan(int idArchivo)
        {
            IList<UsuarioInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var ids = (from usuarioArchivo in context.MIAP_USUARIO_ARCHIVO
                           where usuarioArchivo.ID_ARCHIVO == idArchivo && usuarioArchivo.ES_CARGA
                           select usuarioArchivo.ID_USUARIO).ToList();

                var query = from usuario in context.usp_ObtenDatosUsuarioSistema(null, null)
                            where ids.Contains(usuario.ID_USUARIO)
                            select new UsuarioInfo
                            {
                                IdentificadorPortal = usuario.Clave,
                                IdUsuario = usuario.ID_USUARIO,
                                NombreUsuario = usuario.Nombre,
                                AliasUsuario = usuario.Usuario,
                                ApellidoMaterno = usuario.ApellidoMaterno,
                                ApellidoPaterno = usuario.ApellidoPaterno,
                                EstaActivo = usuario.Activo,
                                Area = usuario.Area,
                                SubArea = usuario.SubArea
                            };
                result = query.ToList();
            }

            return result;
        }

        /// <summary>
        /// Agrega un nuevo usuario a la tabla de usuarios sin perfiles
        /// </summary>
        /// <param name="usuario">Usuario que será agregado.</param>
        /// <param name="user">Usuario que ejecuta la operación.</param>
        public void AddNewSingleUsuario(UsuarioInfo usuario, string user)
        {
            var activo = Enum.GetName(typeof(Estatus), Estatus.Activo);
            using (var context = new MIAPDBEntities())
            {
                var miapUsuario = new MIAP_USUARIO
                {
                    ID_PORTAL = usuario.IdentificadorPortal,
                    ACTIVO = usuario.Estatus == activo,
                    USUARIO_CREACION = user,
                    USUARIO_ACTUALIZACION = user,
                    FECHA_ACTUALIZACION = DateTime.Now,
                    FECHA_CREACION = DateTime.Now
                };

                context.MIAP_USUARIO.Add(miapUsuario);

                context.SaveChanges();
            }
        }

        /// <summary>
        /// Modifica la información del usuario.
        /// </summary>
        /// <param name="usuario">Información del usuario que será modificado.</param>
        /// <param name="user">Usuario que ejecuta la operación.</param>
        public void EditUsuario(UsuarioInfo usuario, string user)
        {
            using (var context = new MIAPDBEntities())
            {
                var miapUsuario = (from usuarioPerfil in context.MIAP_USUARIO_PERFIL
                             where usuarioPerfil.ID_USUARIO == usuarioPerfil.ID_USUARIO
                             select usuarioPerfil).Single();

                // Actualizar la tabla de Usuario_Perfil.
                miapUsuario.ID_PERFIL = usuario.IdPerfil;
                miapUsuario.PUEDE_EJECUTAR_PROYECTO = usuario.PuedeEjecutarProyecto;
                miapUsuario.FECHA_ACTUALIZACION = DateTime.Now;
                miapUsuario.USUARIO_ACTUALIZACION = user;

                context.SaveChanges();
            }
        }

        /// <summary>
        /// Comprueba si el usuario especificado existe en la aplicacion.
        /// </summary>
        /// <param name="nombreUsuario">Nombre de usuario de la credencial.</param>
        /// <returns>true si la credencial de usuario existe.</returns>
        public bool ExisteUsuario(string nombreUsuario)
        {
            bool existe;

            using (var context = new MIAPDBEntities())
            {
                var query = context.usp_ValidaUsuario(nombreUsuario).SingleOrDefault();
                var result = query;
                existe = result.HasValue && result.Value != 0;
            }
            return existe;
        }       
    }
}
